package m.system.db;

import m.system.cache.CacheUtil;
import m.system.listener.InitListener;
import m.system.util.StringUtil;
import m.system.util.SystemUtil;

import java.sql.Connection;
import java.sql.SQLException;
/**
 * 最外层事务生效
 * @author Administrator
 *
 */
public class TransactionManager {
	//定义ThreadLocal静态变量，确定存取类型为Connection
	private static final ThreadLocal<Connection> dbConnection = new ThreadLocal<>();
	private static final ThreadLocal<Boolean> dbRun = new ThreadLocal<>();
	private static final ThreadLocal<Boolean> dbRollback = new ThreadLocal<>();
	
	private Boolean isRun=false;
	private String synchKey;
	public TransactionManager(){
		if(null==dbRun.get()){
			dbRun.set(false);
		}
	}
	/**
	 * 线程开始   初始化数据库连接
	 *  MException
	 */
	public static void initConnection() {
		if(null!=dbConnection.get()) return;
		Connection conn=DBConnection.get();
		if(null!=conn){
			try {//设置自动提交
				conn.setAutoCommit(true);
			} catch (SQLException e) {
				e.printStackTrace();
			}
			//将Connection设置到ThreadLocal
			dbConnection.set(conn);
		}else{
			try {
				Thread.sleep(100);
			} catch (InterruptedException ignored) {}
			initConnection();
		}
	}

	/**
	 * 线程结束前 关闭数据库连接
	 */
	public static void closeConnection() {
		DBConnection.close();
		dbConnection.remove(); 
	}
	/**
	 * 停止应用的时候调用 关闭所有连接  
	 */
	public static void closeAllConection() {
		DBConnection.closeAll();
	}
	protected static Connection getConnection() {
		try {
			InitListener.initDB(null);
			initConnection();
		} catch (Exception e) {
			SystemUtil.printErr(e.getMessage());
		}
		return dbConnection.get();
	}


	/**
	 * 事务开始
	 *  SQLException 
	 */
	public boolean begin() throws SQLException { 
		if(!dbRun.get()&&!isRun){
			dbRun.set(true);
			isRun=true;
			Connection conn = getConnection();
			if (conn.getAutoCommit()) {
				conn.setAutoCommit(false); //手动提交
			}
			return true;
		}else {
			return false;
		}
	}
	/**
	 * 开始事务 
	 *  key 唯一执行主键 20个长度
	 *  Exception
	 */
	public boolean begin(String key) throws Exception {
		if(!StringUtil.isSpace(key)) {
			CacheUtil.initSynch(key);
			synchKey=CacheUtil.executeSynch(key);
		}
		return begin();
	}
	 
	/** 
	 * 事务提交 
	 *  SQLException 
	 */
	public void commit() throws SQLException {
		if(dbRun.get()&&isRun){
			if(null!=dbRollback.get()&&dbRollback.get()) {
				throw new SQLException("事务已回滚");
			}
			dbRun.remove();
			isRun=false;
			Connection conn = getConnection();
			if (!conn.getAutoCommit()) {
				conn.commit();
				conn.setAutoCommit(true);
			}
		}
		if(!StringUtil.isSpace(synchKey)) {
			CacheUtil.releaseSynch(synchKey);
			synchKey=null;
		}
	}

	/** 
	 * 事务回滚 
	 *  SQLException 
	 */
	public void rollback() {
		if(dbRun.get()&&isRun){
			dbRun.remove();
			dbRollback.remove();
			isRun=false;
			Connection conn = getConnection();
			try {
				if (!conn.getAutoCommit()) {
					conn.rollback();
					conn.setAutoCommit(true);
				}
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}else {
			dbRollback.set(true);
		}
		if(!StringUtil.isSpace(synchKey)) {
			CacheUtil.releaseSynch(synchKey);
			synchKey=null;
		}
	}
}
